import {CancelToken as Ct, CancelExecutor, CancelTokenSource, Canceler} from '../types';
import Cancel from './Cancel'

interface ResolvePromise {
  (reason?: Cancel): void
}

export default class CancelToken implements Ct{
  promise: Promise<Cancel>
  reason?: Cancel
  
  constructor(executor: CancelExecutor) {
    let resolvePromise:ResolvePromise
    this.promise = new Promise<Cancel>(resolve => {
      resolvePromise = resolve
    })

    executor((message) => {
      if(this.reason) {
        return
      }
      this.reason = new Cancel(message)
      resolvePromise(this.reason)
    })

  }

  throwIfRequested(){
    if(this.reason){
      throw this.reason
    }
  }

  static source():CancelTokenSource{
    let cancel!: Canceler
    const token = new CancelToken((c) => {
      cancel = c
    })
    return {
      cancel,
      token
    }
  }
}